Source for file SC_Product.php
Documentation is available at SC_Product.php
* This file is part of EC-CUBE
* Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
* http://www.lockon.co.jp/
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* @author LOCKON CO.,LTD.
* @author Kentaro Ohkouchi
* @version $Id: SC_Product.php 21263 2011-09-28 07:15:05Z nanasess $
* ただし指定できるテーブルはproduct_idを持っているテーブルであることが必要.
* @param string $col 並び替えの基準とするフィールド
* @param string $table 並び替えの基準とするフィールドがあるテーブル
* @param string $order 並び替えの順序 ASC / DESC
$this->arrOrderData = array('col' => $col, 'table' => $table, 'order' => $order);
* SC_Queryインスタンスに設定された検索条件を元に並び替え済みの検索結果商品IDの配列を取得する。
* 検索条件は, SC_Query::setWhere() 関数で設定しておく必要があります.
* @param SC_Query $objQuery SC_Query インスタンス
* @param array $arrVal 検索パラメーターの配列
JOIN dtb_products_class AS T1
ON alldtl.product_id = T1.product_id
JOIN dtb_product_categories AS T2
ON alldtl.product_id = T2.product_id
ON T2.category_id = dtb_category.category_id
$objQuery->setGroupBy('alldtl.product_id');
WHERE T2.product_id = alldtl.product_id
ORDER BY T2. $o_col $o_order
$objQuery->setOrder($order);
$results = $objQuery->select('alldtl.product_id', $table, "", $arrVal,
foreach ($results as $val) {
$resultValues[] = $val[0];
* SC_Queryインスタンスに設定された検索条件をもとに対象商品数を取得する.
* 検索条件は, SC_Query::setWhere() 関数で設定しておく必要があります.
* @param SC_Query $objQuery SC_Query インスタンス
* @param array $arrVal 検索パラメーターの配列
JOIN dtb_product_categories AS T2
ON alldtl.product_id = T2.product_id
ON T2.category_id = dtb_category.category_id
$objQuery->setGroupBy('alldtl.product_id');
$sql_base = $objQuery->getSql('alldtl.product_id',$table);
return $objQuery->getOne( "SELECT count(*) FROM ( $sql_base ) as t" , $arrVal);
* SC_Queryインスタンスに設定された検索条件をもとに商品一覧の配列を取得する.
* 主に SC_Product::findProductIds() で取得した商品IDを検索条件にし,
* SC_Query::setOrder() や SC_Query::setLimitOffset() を設定して, 商品一覧
* @param SC_Query $objQuery SC_Query インスタンス
function lists(&$objQuery) {
$where = 'dtb_products_class.del_flg = 0';
$res = $objQuery->select($col, $this->alldtlSQL($where));
* SC_Query::setOrder() や SC_Query::setLimitOffset() を設定して, 商品一覧
* FIXME: 呼び出し元で設定した、SC_Query::setWhere() も有効に扱いたい。
* @param SC_Query $objQuery SC_Query インスタンス
* @param array|int$arrProductId 商品ID
if (empty($arrProductId)) {
$where .= ' AND alldtl.del_flg = 0';
$objQuery->setWhere($where, $arrProductId);
$arrRet = $this->lists($objQuery);
* @param integer $productId 商品ID
* @return array 商品詳細情報の配列
$objQuery = & SC_Query_Ex::getSingletonInstance();
$result = $objQuery->select("*", $this->alldtlSQL("product_id = ? AND del_flg = 0"),
array($productId, $productId));
* @param integer $productClassId 商品規格ID
* @return array 商品詳細情報と商品規格の配列
* 商品IDに紐づく商品規格を自分自身に設定する.
* 引数の商品IDの配列に紐づく商品規格を取得し, 自分自身のフィールドに
* @param array $arrProductId 商品ID の配列
* @param boolean $has_deleted 削除された商品規格も含む場合 true; 初期値 false
$arrProductsClass = array();
foreach ($arrProductId as $productId) {
$classCats1['__unselected'] = '選択してください';
isset ($arrProductClass[0]['class_name1'])
? $arrProductClass[0]['class_name1']
isset ($arrProductClass[0]['class_name2'])
? $arrProductClass[0]['class_name2']
$this->classCat1_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id1']));
$this->classCat2_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id2']));
$classCategories = array();
$classCategories['__unselected']['__unselected']['name'] = '選択してください';
$classCategories['__unselected']['__unselected']['product_class_id'] = $arrProductClass[0]['product_class_id'];
$classCategories['__unselected']['__unselected']['product_type'] = $arrProductClass[0]['product_type_id'];
$this->product_class_id[$productId] = $arrProductClass[0]['product_class_id'];
$this->product_type[$productId] = $arrProductClass[0]['product_type_id'];
foreach ($arrProductClass as $productsClass) {
$productsClass1 = $productsClass['classcategory_id1'];
$productsClass2 = $productsClass['classcategory_id2'];
$stock_find_class = ($productsClass['stock_unlimited'] || $productsClass['stock'] > 0);
$classCats2['classcategory_id2'] = $productsClass2;
$classCats2['name'] = $productsClass['classcategory_name2'] . ($stock_find_class ? '' : ' (品切れ中)');
$classCats2['stock_find'] = $stock_find_class;
if (!in_array($classcat_id1, $classCats1)) {
$classCats1[$productsClass1] = $productsClass['classcategory_name1']
. ($productsClass2 == 0 && !$stock_find_class ? ' (品切れ中)' : '');
= strlen($productsClass['price01'])
? number_format(SC_Helper_DB_Ex::sfCalcIncTax($productsClass['price01']))
= strlen($productsClass['price02'])
? number_format(SC_Helper_DB_Ex::sfCalcIncTax($productsClass['price02']))
= number_format(SC_Utils_Ex::sfPrePoint($productsClass['price02'], $productsClass['point_rate']));
$classCats2['product_code'] = $productsClass['product_code'];
$classCats2['product_class_id'] = $productsClass['product_class_id'];
$classCats2['product_type'] = $productsClass['product_type_id'];
// #929(GC8 規格のプルダウン順序表示不具合)対応のため、2次キーは「#」を前置
if (SC_Utils_Ex::isBlank($productsClass1)) {
$productsClass1 = '__unselected2';
$classCategories[$productsClass1]['#'] = array(
'classcategory_id2' => '',
$classCategories[$productsClass1]['#' . $productsClass2] = $classCats2;
* SC_Query インスタンスに設定された検索条件を使用して商品規格を取得する.
* @param SC_Query $objQuery SC_Queryインスタンス
* @param array $params 検索パラメーターの配列
T2.parent_class_combination_id,
T3.name AS classcategory_name,
LEFT JOIN dtb_class_combination T2
ON T1.class_combination_id = T2.class_combination_id
LEFT JOIN dtb_classcategory T3
ON T2.classcategory_id = T3.classcategory_id
ON T3.class_id = T4.class_id
$objQuery->setOrder('T3.rank DESC'); // XXX
$arrRet = $objQuery->select($col, $table, "", $params);
foreach ($arrRet as $rows) {
$levels[] = $rows['level'];
$parents[] = $rows['parent_class_combination_id'];
for ($i = 0; $i < $level - 1; $i++ ) {
$objQuery = & SC_Query_Ex::getSingletonInstance();
$objQuery->setWhere('T1.class_combination_id IN (' . implode(', ', array_pad(array(), count($parents), '?')) . ')');
T1.parent_class_combination_id,
T2.name AS classcategory_name,
LEFT JOIN dtb_classcategory T2
ON T1.classcategory_id = T2.classcategory_id
ON T2.class_id = T3.class_id
$objQuery->setOrder('T2.rank DESC'); // XXX
$arrParents = $objQuery->select($col, $table, "", $parents);
foreach ($arrParents as $rows) {
$parents[] = $rows['parent_class_combination_id'];
foreach ($arrRet as $child) {
if ($child['parent_class_combination_id']
== $rows['class_combination_id']) {
$rows['product_id'] = $child['product_id'];
$parentsClass = array_merge($parentsClass, $tmpParents);
foreach ($tmpClass as $val) {
$val['class_id' . $val['level']] = $val['class_id'];
$val['class_name' . $val['level']] = $val['class_name'];
$val['classcategory_name' . $val['level']] = $val['classcategory_name'];
$val['classcategory_id' . $val['level']] = $val['classcategory_id'];
$arrProductsClass[] = $val;
return $arrProductsClass;
* @param integer $productClassId 商品規格ID
$objQuery = & SC_Query_Ex::getSingletonInstance();
$objQuery->setWhere('product_class_id = ? AND T1.del_flg = 0');
$objQuery->setOrder("T2.level DESC");
$productsClass = $this->getProductsClassFull($results);
return $productsClass[0];
* 複数の商品IDに紐づいた, 商品規格を取得する.
* @param array $productIds 商品IDの配列
* @param boolean $has_deleted 削除された商品規格も含む場合 true; 初期値 false
if (empty($productIds)) {
$objQuery = & SC_Query_Ex::getSingletonInstance();
$where .= ' AND T1.del_flg = 0';
$objQuery->setWhere($where);
$objQuery->setOrder("T2.level DESC");
* 商品IDに紐づいた, 商品規格を階層ごとに取得する.
* @param array $productId 商品ID
* @return array 階層ごとの商品規格の配列
return $this->getProductsClassLevel($results);
* 商品IDに紐づいた, 商品規格をすべての組み合わせごとに取得する.
* @param array $productId 商品ID
* @param boolean $has_deleted 削除された商品規格も含む場合 true; 初期値 false
* @return array すべての組み合わせの商品規格の配列
return $this->getProductsClassFull($results);
* 商品規格の配列から, 商品規格を階層ごとに取得する.
* @param array $productsClassResults 商品規格の結果の配列
* @return array 階層ごとの商品規格の配列
function getProductsClassLevel($productsClassResults) {
foreach ($productsClassResults as $row) {
$productsClassLevel['level' . $row['level']][] = $row;
return $productsClassLevel;
* 商品規格の配列から, 商品規格のすべての組み合わせを取得する.
* @param array $productsClassResults 商品規格の結果の配列
function getProductsClassFull($productsClassResults) {
$results = $this->getProductsClassLevel($productsClassResults);
$productsClass = array();
if (SC_Utils_Ex::isBlank($results["level1"])
&& SC_Utils_Ex::isBlank($results["level2"])) {
return $results['level'];
foreach ($results["level1"] as $level1) {
foreach ($results["level2"] as $level2) {
if ($level2['parent_class_combination_id'] == $level1['class_combination_id']) {
$productsClass[] = $level1;
* 商品IDをキーにした, 商品ステータスIDの配列を取得する.
* @return array 商品IDをキーにした商品ステータスIDの配列
if (empty($productIds)) {
$objQuery = & SC_Query_Ex::getSingletonInstance();
$cols = 'product_id, product_status_id';
$from = 'dtb_product_status';
$where = 'del_flg = 0 AND product_id IN (' . implode(', ', array_pad(array(), count($productIds), '?')) . ')';
$productStatus = $objQuery->select($cols, $from, $where, $productIds);
foreach ($productStatus as $status) {
$results[$status['product_id']][] = $status['product_status_id'];
* TODO 現在は DELETE/INSERT だが, UPDATE を検討する.
* @param integer $productId 商品ID
* @param array $productStatusIds ON にする商品ステータスIDの配列
$val['product_id'] = $productId;
$val['creator_id'] = $_SESSION['member_id'];
$val['create_date'] = 'CURRENT_TIMESTAMP';
$val['update_date'] = 'CURRENT_TIMESTAMP';
$objQuery = & SC_Query_Ex::getSingletonInstance();
$objQuery->delete('dtb_product_status', 'product_id = ?', array($productId));
foreach ($productStatusIds as $productStatusId) {
if($productStatusId == '') continue;
$val['product_status_id'] = $productStatusId;
$objQuery->insert('dtb_product_status', $val);
* getDetailAndProductsClass() の結果から, 購入制限数を取得する.
* @param array $p 商品詳細の検索結果の配列
* @return integer 商品詳細の結果から求めた購入制限数.
* @see getDetailAndProductsClass()
if ($p['stock_unlimited'] != '1' && is_numeric($p['sale_limit'])) {
$limit = min($p['sale_limit'], $p['stock']);
$limit = $p['sale_limit'];
} elseif ($p['stock_unlimited'] != '1') {
* 減少させた結果, 在庫数が 0 未満になった場合, 引数 $quantity が 0 の場合は,
* 在庫の減少に成功した場合は true を返す.
* @param integer $productClassId 商品規格ID
* @param integer $quantity 減少させる在庫数
* @return boolean 在庫の減少に成功した場合 true; 失敗した場合 false
$objQuery = & SC_Query_Ex::getSingletonInstance();
$objQuery->update('dtb_products_class', array(),
"product_class_id = ?", array($productClassId),
array('stock' => 'stock - ?'), array($quantity));
if ($productsClass['stock_unlimited'] != '1' && $productsClass['stock'] < 0) {
* この関数は, 主にスマートフォンで使用します.
* @param array $arrProducts 商品情報の配列
* @return array 税込金額を設定した商品情報の配列
foreach ($arrProducts as $key=> $val) {
$arrProducts[$key]['price01_min_format'] = number_format($arrProducts[$key]['price01_min']);
$arrProducts[$key]['price01_max_format'] = number_format($arrProducts[$key]['price01_max']);
$arrProducts[$key]['price02_min_format'] = number_format($arrProducts[$key]['price02_min']);
$arrProducts[$key]['price02_max_format'] = number_format($arrProducts[$key]['price02_max']);
$arrProducts[$key]['price01_min_tax_format'] = number_format($arrProducts[$key]['price01_min_tax']);
$arrProducts[$key]['price01_max_tax_format'] = number_format($arrProducts[$key]['price01_max_tax']);
$arrProducts[$key]['price02_min_tax_format'] = number_format($arrProducts[$key]['price02_min_tax']);
$arrProducts[$key]['price02_max_tax_format'] = number_format($arrProducts[$key]['price02_max_tax']);
* @param string $where 商品詳細の WHERE 句
* @return string 商品詳細の SQL
if (!SC_Utils_Ex::isBlank($where)) {
$where_clause = " WHERE " . $where;
* point_rate, deliv_fee は商品規格(dtb_products_class)ごとに保持しているが,
* 商品(dtb_products)ごとの設定なので MAX のみを取得する.
,dtb_products.main_list_comment
,dtb_products.main_list_image
,dtb_products.main_comment
,dtb_products.main_large_image
,dtb_products.sub_comment1
,dtb_products.sub_large_image1
,dtb_products.sub_comment2
,dtb_products.sub_large_image2
,dtb_products.sub_comment3
,dtb_products.sub_large_image3
,dtb_products.sub_comment4
,dtb_products.sub_large_image4
,dtb_products.sub_comment5
,dtb_products.sub_large_image5
,dtb_products.sub_comment6
,dtb_products.sub_large_image6
,dtb_products.create_date
,dtb_products.update_date
,dtb_products.deliv_date_id
,dtb_maker.name AS maker_name
MIN(product_code) AS product_code_min,
MAX(product_code) AS product_code_max,
MIN(price01) AS price01_min,
MAX(price01) AS price01_max,
MIN(price02) AS price02_min,
MAX(price02) AS price02_max,
MIN(stock_unlimited) AS stock_unlimited_min,
MAX(stock_unlimited) AS stock_unlimited_max,
MAX(point_rate) AS point_rate,
MAX(deliv_fee) AS deliv_fee,
ON dtb_products.product_id = T4.product_id
ON dtb_products.maker_id = dtb_maker.maker_id
* MEMO: 2.4系 vw_product_classに相当(?)するイメージ
* @param string $where 商品詳細の WHERE 句
* @return string 商品規格詳細の SQL
if (!SC_Utils_Ex::isBlank($where)) {
$where_clause = " WHERE " . $where;
dtb_products_class.product_class_id,
dtb_products_class.class_combination_id,
dtb_products_class.product_type_id,
dtb_products_class.product_code,
dtb_products_class.stock,
dtb_products_class.stock_unlimited,
dtb_products_class.sale_limit,
dtb_products_class.price01,
dtb_products_class.price02,
dtb_products_class.deliv_fee,
dtb_products_class.point_rate,
dtb_products_class.down_filename,
dtb_products_class.down_realfilename,
dtb_class_combination.parent_class_combination_id,
dtb_class_combination.classcategory_id,
dtb_class_combination.level as classlevel,
Tpcm.classcategory_id as parent_classcategory_id,
Tpcm.level as parent_classlevel,
Tcc1.class_id as class_id,
Tcc1.name as classcategory_name,
Tcc2.class_id as parent_class_id,
Tcc2.name as parent_classcategory_name
LEFT JOIN dtb_products_class
ON dtb_products.product_id = dtb_products_class.product_id
LEFT JOIN dtb_class_combination
ON dtb_products_class.class_combination_id = dtb_class_combination.class_combination_id
LEFT JOIN dtb_class_combination as Tpcm
ON dtb_class_combination.parent_class_combination_id = Tpcm.class_combination_id
LEFT JOIN dtb_classcategory as Tcc1
ON dtb_class_combination.classcategory_id = Tcc1.classcategory_id
LEFT JOIN dtb_classcategory as Tcc2
ON Tpcm.classcategory_id = Tcc2.classcategory_id
* 商品規格ID1、2に紐づいた,product_class_idを取得する.
* @param int $productId 商品ID
* @param int $classcategory_id1 商品規格ID1
* @param int $classcategory_id2 商品規格ID2
* @return string product_class_id
$objQuery = new SC_Query_Ex();
$col = "T1.product_id AS product_id,T1.product_class_id AS product_class_id,T1.classcategory_id1 AS classcategory_id1,T1.classcategory_id2 AS classcategory_id2";
pc.product_code AS product_code,
pc.product_id AS product_id,
pc.product_class_id AS product_class_id,
pc.class_combination_id AS class_combination_id,
COALESCE(cc2.classcategory_id,0) AS classcategory_id1,
COALESCE(cc1.classcategory_id,0) AS classcategory_id2
dtb_products_class pc LEFT JOIN dtb_class_combination cc1 ON pc.class_combination_id = cc1.class_combination_id
LEFT JOIN dtb_class_combination cc2 ON cc1.parent_class_combination_id = cc2.class_combination_id) T1
$where = "T1.product_id = ? AND T1.classcategory_id1 = ? AND T1.classcategory_id2 = ?";
$arrRet = $objQuery->select($col, $table, $where,
array($productId, $classcategory_id1, $classcategory_id2));
return $arrRet[0]['product_class_id'];
Documentation generated on Fri, 24 Feb 2012 14:02:53 +0900 by Seasoft
|